##### pyhon内存管理
# python中每个对象都有一个ob_ref的字段，用来计数该对象当前的引用次数
# 当有新的引用指向该对象的时候，ob_ref会加1
# 当这个引用指向其他对象的时候，ob_ref会减1
# del+变量名 可以减少引用
# 对象指的是存储在内存中的一段数据
# 当ob_ref为零时，就会触发垃圾回收，释放内存
# 交互模式下：
# >>> x = [1]           --》 [1]引用了一次
# >>> y = [2]
# >>> getrefcount(x)    --》 临时创建了一次引用，[1]引用了2次
# 2
# >>> getrefcount(y)
# 2
# >>> x.append(y)
# >>> x                 --》 输出x，[1]引用了2次
# [1, [2]]
# >>> getrefcount(x)    --》 临时创建了一次引用，[1]引用了3次
# 3
# >>> y.append(x)
# >>> y
# [2, [1, [...]]]
# >>> getrefcount(y)
# 4
# >>>


# --------------------------------------------------------------------
#### 循环引用
# 内存泄露：某部分内存分配出去之后，无法回收，无法释放
# 内存溢出：oom（out of memory），用的太多，给的太少
#### 为了解决循环引用的问题：
### 垃圾回收：
## 1、分代回收：
# import gc
# gc.get_threshold()
# (700, 10, 10)
## 2、标记清除：
# 标记 清除
# python的内存管理是引用计数为主，分代回收和标记清除为辅


# --------------------------------------------------------------------
#### python缓冲池
## 整数对象缓冲池：对于[-5, 256]这样的小整数我们缓冲池已经提前申请了一块内存空间
# 像 a = 1 和 b = 1 他们的id内存地址是一样的
# 但是超过这一范围，内存地址不一样
## 字符串驻留区：
# 特殊字符如果是单个会放在驻留区
# >>> a = '!'
# >>> b = '!'
# >>> a is b
# True
# 不包含特殊字符的字符串都会放在驻留区
# >>> a = 'abcdefg'
# >>> b = 'abcdefg'
# >>> a is b
# True
# >>>
# 用*去乘，当字符串的字符数超过20个就不行


####
# ---------------------------------------------------------------------
# 以字典的容器包裹容器为例 --》 value是列表
## 浅拷贝：
# dict = {key: []}
# dict1 = dict.copy()
# dict is dict1 --> 结果是False
# 但是dict[key] is dict1[key] --> 就是列表内存地址是一样的
# 这就是浅拷贝，只是拷贝第一层的数据，不会和原来的产生关联，但是列表还是会产生关联
# 即改变dict[key]，dict1[key]也会发生相同的改变

## 深拷贝：
# import copy
# dict = {key: []}
# dict1 = copy.deepcopy()
# dict is dict2  -->结果是False
# dict[key] is dict1[key] -->结果是False
# 即两者之间不会产生关联了,一个发生改变,另一个也不会发生改变,第一层和第二层的内存地址都改变了
# 都是在内存中重新创建一个新的内存地址